﻿using System;
using System.Linq;
using RiskMan.Config;
using RiskMan.DataClass.Models.Quik;
using RiskMan.Models;

namespace RiskMan.DataClass.Models.RM
{
    public enum StatusEnum
    {
        WAIT = 0,
        WORK = 1
    }

    public class ModuleInvestorModel : ViewModelBase
    {
        #region Model

        #region private

        private bool _considerVmnd;
        private double _comisBlock;
        private bool _runComicBlock;

        private bool _check;
        private bool _run;
        private string _account;
        private string _clientCode;
        private double _deposite;
        private double _drowdown;
        private string _typeCalc;
        private string _typeLimite;
        private double _typeGo = 1;

        private double _currentBalance;
        private double _lockBalance;
        private double _profitLoss;
        private double _commis;
        private double _full;
        private double _fullPerSent;

        #endregion

        #region public

        public bool ConsiderVMND 
        {
            get { return _considerVmnd; }
            set 
            {
                _considerVmnd = value;
            }
        }
        public double ComisBlock 
        {
            get { return _comisBlock; }
            set 
            {
                _comisBlock = value;
            }
        }
        public bool RunComicBlock
        {
            get { return _runComicBlock; }
            set 
            {
                _runComicBlock = value;
            }
        }

        public bool Check
        {
            get { return _check; }
            set
            {
                if ( _check != value )
                {
                    _check = value;
                    OnPropertyChanged( "Check" );
                }
            }
        }
        public bool Run
        {
            get { return _run; }
            set
            {
                if ( _run != value )
                {
                    _run = value;
                    OnPropertyChanged( "Run" );
                }
            }
        }
        public string Account
        {
            get { return _account; }
            set
            {
                if ( _account != value )
                {
                    _account = value;
                    OnPropertyChanged( "Account" );
                }
            }
        }
        public string ClientCode
        {
            get { return _clientCode; }
            set
            {
                if ( _clientCode != value )
                {
                    _clientCode = value;
                    OnPropertyChanged( "ClientCode" );
                }
            }
        }
        public double Deposite
        {
            get { return _deposite; }
            set
            {
                if ( _deposite != value )
                {
                    _deposite = value;
                    OnPropertyChanged( "Deposite" );
                }
            }
        }
        public double Drowdown
        {
            get { return _drowdown; }
            set
            {
                if ( _drowdown != value )
                {
                    _drowdown = value;
                    OnPropertyChanged( "Drowdown" );
                }
            }
        }
        public string TypeCalc
        {
            get { return _typeCalc; }
            set
            {
                if ( _typeCalc != value )
                {
                    _typeCalc = value;
                    OnPropertyChanged( "TypeCalc" );
                }
            }
        }
        public string TypeLimite
        {
            get { return _typeLimite; }
            set
            {
                if ( _typeLimite != value )
                {
                    _typeLimite = value;
                    OnPropertyChanged( "TypeLimite" );
                }
            }
        }
        public double TypeGO
        {
            get { return _typeGo; }
            set
            {
                if ( _typeGo != value )
                {
                    _typeGo = value;
                    OnPropertyChanged( "TypeGO" );
                }
            }
        }

        public double CurrentBalance
        {
            get { return _currentBalance; }
            set
            {
                if ( _currentBalance != value )
                {
                    _currentBalance = value;
                    OnPropertyChanged( "CurrentBalance" );
                }
            }
        }
        public double LockBalance
        {
            get { return _lockBalance; }
            set
            {
                if ( _lockBalance != value )
                {
                    _lockBalance = value;
                    OnPropertyChanged( "LockBalance" );
                }
            }
        }
        public double ProfitLoss
        {
            get { return _profitLoss; }
            set
            {
                if ( _profitLoss != value )
                {
                    _profitLoss = value;
                    OnPropertyChanged( "ProfitLoss" );
                }
            }
        }
        public double Commis
        {
            get { return _commis; }
            set
            {
                if ( _commis != value )
                {
                    _commis = value;
                    OnPropertyChanged( "Commis" );
                }
            }
        }
        public double Full
        {
            get { return _full; }
            set
            {
                if ( _full != value )
                {
                    _full = value;
                    OnPropertyChanged( "Full" );
                }
            }
        }
        public double FullPerSent
        {
            get { return _fullPerSent; }
            set
            {
                if ( _fullPerSent != value )
                {
                    _fullPerSent = value;
                    OnPropertyChanged( "FullPerSent" );
                }
            }
        }

        #endregion

        #endregion

        public ModuleInvestorModel ( )
        {
        
        }

        public void Terminals_OnTerminalsTransaction ( object error, int tid, double orderId, string msgError )
        {
            if ( orderId == 0 )
            {
                if ( Order != null )
                {
                    if ( tid == Order.Tid )
                        Order = null;
                }

                if ( SOrder != null )
                {
                    if ( tid == SOrder.TID )
                        SOrder = null;
                }
            }
        }

        private Data _data;

        public int Tid = 0;
        public StopOrderModel SOrder;
        public OrderModel Order;

        #region статус работы робота

        /// <summary>
        /// WAIT - ожидание обновления статуса посланой транзакции
        /// WORK - робот запущен и работает
        /// </summary>
        private StatusEnum _status;
        public StatusEnum Status
        {
            get { return _status; }
            set
            {
                //      if (value == StatusEnum.WAIT)
                _status = value;
            }
        }

        #endregion

        #region проверка просадки надо или нет блокировать

        internal bool Calc ( )
        {
            _data = MainWindow.StaticRiskMan._dataProvider;

            Commis = GetComiss( );
            ProfitLoss = GetProfit( );
            CurrentBalance = GetDeposite( );

            Full = CurrentBalance - Deposite;
            FullPerSent = ( ( CurrentBalance - Deposite ) / Deposite ) * 100;

            bool _lock = false;
            if ( this.TypeCalc == "Рубли" )
            {
                if ( Full < -Drowdown )
                {
                    _lock = true;
                }
            }
            else
                if ( FullPerSent < -Drowdown )
                    _lock = true;
            return _lock;
        }

        #endregion

        #region Текущий баланс

        private double GetDeposite ( )
        {
            if ( Account == ClientCode )
            {
                if ( ConsiderVMND == true && ProfitLoss > 0 )
                    return GetLimitOpenPos( ) - Commis;
            }
            return GetLimitOpenPos( ) + ProfitLoss - Commis;
        }

        private double GetLimitOpenPos ( )
        {
            if ( _account == _clientCode )
            {
                var ac = _data.LimitebyAccount.Where( a => a.Account == _account ).ToList( );

                for ( int i = 0; i < ac.Count; i++ )
                {
                    if ( ac [ i ].LimitOpenPosition == 0 )
                    {
                        for ( int j = 0; j < _data.Portfel.Count; j++ )
                        {
                            if ( _data.Portfel [ j ].SrochAccount == _clientCode )
                            {
                                return _data.Portfel [ j ].EnterSredstva;
                            }
                        }
                    }
                    else
                        return ac [ i ].LimitOpenPosition;
                }
            }
            else
            {
                for ( int i = 0; i < _data.Portfel.Count; i++ )
                {
                    if ( _data.Portfel [ i ].CodeClient == _clientCode )
                    {
                        return _data.Portfel [ i ].EnterSredstva;
                    }
                }
            }

            return 0;
        }

        #endregion

        #region Комиссия

        private double GetComiss ( )
        {
            int count = 0;

            if ( _account == _clientCode )
            {
                for ( int i = 0; i < _data.FortsPositionsList.Count; i++ )
                {
                    if ( _data.FortsPositionsList [ i ].Account == _account &&
                        _data.FortsPositionsList [ i ].Company.Substring( 0, 6 ) == "SPBFUT" )
                    {
                        count += _data.FortsPositionsList [ i ].CurrentLongPos + _data.FortsPositionsList [ i ].CurrentShortPos;
                    }
                }
            }
            else
            {
                // ммвб комиссия
                double result = 0;
                double volume = 0;
                for ( int i = 0; i < _data.DealList.Count; i++ )
                {
                    if ( _data.DealList [ i ].Account == _account &&
                         _data.DealList [ i ].ClientCode == _clientCode )
                    {
                        volume += _data.DealList [ i ].Volume;
                    }
                }
                for ( int i = 0; i < _data.MmvbComisList.Count; i++ )
                {
                    if ( volume >= _data.MmvbComisList [ i ].FromComis && volume < _data.MmvbComisList [ i ].ToComis )
                    {
                        result = volume * _data.MmvbComisList [ i ].Comis;
                        break;
                    }
                    else
                    {
                        if ( result == 0 && i == _data.MmvbComisList.Count - 1 )
                            result = volume * _data.MmvbComisList [ i ].Comis;
                    }
                }
                return result / 100;
            }

            return count * RiskMan.Properties.Settings.Default.Commis;
        }

        #endregion

        #region Прибыл/убыток

        private double GetProfit ( )
        {
            if ( _account == _clientCode )
            {
                for ( int i = 0; i < _data.LimitebyAccount.Count; i++ )
                {
                    if ( _data.LimitebyAccount [ i ].TypeLimit != cfg.ZalogMoney )
                        if ( _data.LimitebyAccount [ i ].Account == _account )
                        {
                            return ( _data.LimitebyAccount [ i ].VariableMarga + _data.LimitebyAccount [ i ].Dohod );
                        }
                }
            }
            else
            {

                for ( int i = 0; i < _data.Portfel.Count; i++ )
                {
                    if ( _data.Portfel [ i ].CodeClient == _clientCode )
                        return _data.Portfel [ i ].ProfitLoss;
                }
            }

            return 0;
        }

        #endregion

        //#region закрытие позиций и проверка блокирующей заявки на корректность

        //internal void CheckLockOrder ( )
        //{
        //    ClosePositions( );

        //    LockBalance = ( int ) ( GetQuantity
        //                        (
        //                            GetGo( ) / TypeGO
        //                        ) ) - 1;

            //if ( LockBalance > 0 )
            //{
            //    if ( _account == _clientCode )
            //    {
            //        if ( Order == null )
            //        {
            //            SendForts( );
            //            return;
            //        }
            //        if ( Order.Status == cfg.CANCEL ||
            //             Order.Status == cfg.PERFORMED ||
            //             Order.Status == null )
            //        {
            //            SendForts( );
            //            return;
            //        }
            //    }
                //else
                //{
                //    if ( SOrder == null )
                //    {
                //        SendMMVB( );
                //        return;
                //    }
                //    if ( SOrder.Status == cfg.CANCEL ||
                //         SOrder.Status == cfg.PERFORMED ||
                //         SOrder.Status == null )
                //    {
                //        SendMMVB( );
                //        return;
                //    }
                //}
            //}
        //}

        //#endregion

        //#region Forts trans

        //public void SendForts ( )
        //{
        //    Order = new OrderModel( )
        //    {
        //        TID = MainWindow.StaticRiskMan.Terminals.SendOrder
        //        (
        //            _account,
        //            _clientCode,
        //            GetOperation( ),
        //            _data.GetMaxMinPrice( Settings.Default.BlockSeccode, GetOperation( ) ),
        //            ( int ) LockBalance,
        //            Settings.Default.BlockSeccode,
        //            _data.GetClasscode( Settings.Default.BlockSeccode )
        //        ),
        //        Status = cfg.UNKNOWN
        //    };
        //}

        //#endregion

        //#region mmvb trans

        //public void SendMMVB ( )
        //{
        //    SOrder = new StopOrderModel( )
        //    {
        //        TID = MainWindow.StaticRiskMan.Terminals.SendSOWithOtherEmitent(
        //                _data.GetClasscode( Properties.Settings.Default.BlockSeccodeMMVB ),
        //                Properties.Settings.Default.BlockSeccodeMMVB,
        //                _data.GetClasscode( Properties.Settings.Default.BlockSeccodeMMVB ),
        //                Properties.Settings.Default.BlockSeccodeMMVB,
        //                _account,
        //                _clientCode + "//RiskMan",
        //                _data.GetPriceClose( Properties.Settings.Default.BlockSeccodeMMVB ),
        //                _data.GetPriceClose( Properties.Settings.Default.BlockSeccodeMMVB ),
        //                ( int ) LockBalance ),
        //                Status = cfg.UNKNOWN
        //    };

        //}

        //#endregion

        //#region Операция

        //private char GetOperation ( )
        //{
        //    double delta = 0;
        //    double max_delta = 0, min_delta = 0;

        //    for ( int i = 0; i < _data.CurrentList.Count; i++ )
        //    {
        //        if ( _data.CurrentList[i].Seccode == _data.GetClasscode( Properties.Settings.Default.BlockSeccode))
        //        {
        //            max_delta = _data.CurrentList [ i ].MaxPrice - _data.CurrentList [ i ].LastPrice;
        //            min_delta = _data.CurrentList [ i ].LastPrice - _data.CurrentList [ i ].MinPrice;
        //            delta = ( _data.CurrentList [ i ].MaxPrice - _data.CurrentList [ i ].MinPrice ) * 30 / 100;
        //            break;
        //        }
        //    }

        //    if ( max_delta < delta )
        //        return 'B';
        //    if ( min_delta < delta )
        //        return 'S';

        //    return 'S';
        //}

        //#endregion

        //#region количество контрактов/лотов

        //public double GetQuantity ( double go )
        //{
        //    return (CurrentBalance / go) * _data.GetLaverage(_clientCode);
        //}

        //#endregion

        //#region возвращает стоимость одного контракта/лота

        //private double GetGo ( )
        //{
        //    try
        //    {
        //        string seccode = "";

        //        if ( _account == _clientCode )
        //            seccode = RiskMan.Properties.Settings.Default.BlockSeccode;
        //        else
        //            seccode = RiskMan.Properties.Settings.Default.BlockSeccodeMMVB;

        //        for ( int i = 0; i < _data.CurrentList.Count; i++ )
        //        {
        //            if ( _data.CurrentList [ i ].Seccode == seccode )
        //            {
        //                if ( RunComicBlock == true )
        //                {
        //                    if ( _account == _clientCode )
        //                        return _data.CurrentList [ i ].GOSell + ComisBlock;
        //                    else
        //                        return ( _data.CurrentList [ i ].ClosePrice / 2 * _data.CurrentList [ i ].QUANTITY ) * ( 1 + ComisBlock );
        //                }
        //                else
        //                {
        //                    if ( Account == ClientCode )
        //                        return _data.CurrentList [ i ].GOSell;
        //                    else
        //                        return _data.CurrentList [ i ].ClosePrice / 2 * _data.CurrentList [ i ].QUANTITY;
        //                }
        //            }
        //        }
        //    }
        //    catch ( Exception ex )
        //    {
        //        cfg.SetLog( ex.Message, MainWindow.StaticRiskMan.ListBox_Logs, this.GetType( ), MethodBase.GetCurrentMethod( ) );
        //        return 1;
        //    }
        //    return 1;
        //}

        //#endregion

        #region закрытие по рынку

        private void ClosePositions ( )
        {
                if ( _account == _clientCode )
                {
                    #region закрытие позиций всех по порядку

                    for ( int i = 0; i < _data.FortsPositionsList.Count; i++ )
                    {
                        if ( _data.FortsPositionsList [ i ].CurrentEmptyPos != 0 )
                        {
                            Tid = MainWindow.StaticRiskMan.Terminals.SendOrder
                                (
                                    _account,
                                    _clientCode,
                                    _data.FortsPositionsList [ i ].CurrentEmptyPos > 0 ? 'S' : 'B',
                                    _data.GetMaxMinPrice( _data.FortsPositionsList [ i ].Seccode, _data.FortsPositionsList [ i ].CurrentEmptyPos > 0 ? 'B' : 'S' ),
                                    Math.Abs( _data.FortsPositionsList [ i ].CurrentEmptyPos ),
                                    _data.FortsPositionsList [ i ].Seccode,
                                    _data.GetClasscode( _data.FortsPositionsList [ i ].Seccode )
                                );
                            return;
                        }
                    }

                    #endregion
                    #region снятие активных заявок выставленных не системой

                    var list = _data.OrderList.Where( a => a.Account == _account &&
                                                           a.ClientCode == _clientCode &&
                                                           a.Status == cfg.Active ).ToList( );
                    if ( list.Count > 0 )
                    {
                        for ( int j = 0; j < list.Count; j++ )
                        {
                            if ( Order != null )
                                if ( Order.Tid > 0 )
                                    continue;
                            MainWindow.StaticRiskMan.Terminals.CancelOrder
                                    (
                                        list [ j ].Number,
                                        list [ j ].Seccode,
                                        _data.GetClasscode( list [ j ].Seccode ),
                                        list [ j ].Account,
                                        list [ j ].ClientCode
                                    );
                            return;
                        }
                    }

                    #endregion
                }
                else
                {
                    #region закрытие по рынку

                    for ( int i = 0; i < _data.EmitentLimiteList.Count; i++ )
                    {
                        if ( _data.EmitentLimiteList [ i ].Account == _account && _data.EmitentLimiteList [ i ].ClientCode == _clientCode )
                        {
                            char operation = '\0';

                            if ( _data.EmitentLimiteList [ i ].Balance > 0 ) operation = 'S';
                            if ( _data.EmitentLimiteList [ i ].Balance < 0 ) operation = 'B';

                            if ( operation != '\0' )
                            {

                                MainWindow.StaticRiskMan.Terminals.SendMMMarket
                                (
                                    _account,
                                    _clientCode,
                                    operation,
                                    Math.Abs( _data.EmitentLimiteList [ i ].Balance ) / _data.GetLots( _data.EmitentLimiteList [ i ].Seccode ),
                                    _data.EmitentLimiteList [ i ].Seccode,
                                    _data.GetClasscode( _data.EmitentLimiteList [ i ].Seccode )
                                );

                                return;
                            }
                        }
                    }

                    #endregion
                    #region  снятие активных стоп-заявок

                    var activeS = _data.StopOrderList.Where( a => a.TradeAccount == _account &&
                        a.ClientCode == _clientCode && a.Status == cfg.Active ).ToList( );
                    if ( activeS.Count > 0 )
                    {
                        for ( int j = 0; j < activeS.Count; j++ )
                        {
                            bool result = false;

                            //for ( int i = 0; i < _data.StopOrderBlockingItems.Count; i++ )
                            //    if ( activeS [ j ].Number == _data.StopOrderBlockingItems [ i ].Number )
                            //        result = true;

                            if ( result == false )
                            {
                                if ( SOrder != null )
                                    if ( SOrder.TID > 0 )
                                        continue;
                                MainWindow.StaticRiskMan.Terminals.CancelStopOrder(
                                    activeS [ j ].Number,
                                    activeS [ j ].Seccode,
                                    _data.GetClasscode( activeS [ j ].Seccode ),
                                    _account,
                                    _clientCode );

                                return;
                            }
                        }
                    }
                    #endregion
                    #region снятие активных заявок

                    var activeO = _data.OrderList.Where( a => a.Account == _account &&
                                                              a.ClientCode == _clientCode &&
                                                              a.Status == cfg.Active ).ToList( );
                    if ( activeO.Count > 0 )
                    {
                        for ( int i = 0; i < activeO.Count; i++ )
                        {
                            MainWindow.StaticRiskMan.Terminals.CancelOrder(
                                  activeO [ i ].Number,
                                  activeO [ i ].Seccode,
                                  _data.GetClasscode( activeO [ i ].Seccode ),
                                  _account,
                                  _clientCode );

                            return;
                        }
                    }

                    #endregion
            }
        }
        #endregion

        #region Обновление заявок

        internal void Updata ( )
        {
            if ( Order != null )
            {
                for ( int i = 0; i < _data.OrderList.Count; i++ )
                {
                    if ( _data.OrderList [ i ].Tid == Order.Tid )
                        Order = _data.OrderList [ i ];
                }
            }
            if ( SOrder != null )
            {
                for ( int i = 0; i < _data.StopOrderList.Count; i++ )
                {
                    if ( _data.StopOrderList [ i ].TID == SOrder.TID )
                        SOrder = _data.StopOrderList [ i ];
                }
            }
        }

        #endregion 
    }
}
    